using System; using System.Collections.Generic; using System.Linq; using System.Text; using Roslyn.Compilers; using Roslyn.Compilers.CSharp; using System.Reflection; using System.IO; using System.Diagnostics; namespace RoslynEval { public class Eval { Assembly assembly; Type assemblyType; MethodInfo evaluator; public static Func<Double[], Double> CreateEvalFunction(String inEquation, String[] variableNames) { Eval eval = new Eval(inEquation, variableNames); return (Double[] variableValues) => eval.CallAssembly(variableValues); } public Eval(String inEquation, String[] variableNames) { SetAssembly(inEquation, variableNames); } public void SetAssembly(String inEquation,String[] variableNames) { String variableNamesString = VariableNamesToString(variableNames); var text = "using System; class Calc { public static object Eval(" + variableNamesString + ") { return " + inEquation + "; } }"; assembly = CompileAssembly(text); if (assembly == null) { return; } assemblyType = assembly.GetType("Calc"); evaluator = assemblyType.GetMethod("Eval"); } public Double CallAssembly(Double[] variableValues) { if (assembly == null) { return Double.NaN; } object[] objs = Functional.Maps.Map(variableValues, x => (object)x); string answer = evaluator.Invoke(null, objs).ToString(); return StringToDouble(answer); } public static Double StringToDouble(String inString) { Double result; if (Double.TryParse(inString, out result) == true) { return result; } else { return Double.NaN; } } public static String VariableNamesToString(String[] variableNames) { Int32 L; String lOut=""; for (L = 0; L < variableNames.Length; L++) { lOut += "Double " + variableNames[L]; if (L < variableNames.Length - 1) { lOut += ","; } } return lOut; } public static Assembly CompileAssembly(String inCode) { var tree = SyntaxTree.ParseCompilationUnit(inCode); var compilation = Compilation.Create( "calc.dll", options: new CompilationOptions(assemblyKind: AssemblyKind.DynamicallyLinkedLibrary), syntaxTrees: new[] { tree }, references: new[] { new AssemblyFileReference(typeof(object).Assembly.Location) }); Assembly compiledAssembly; var stream = new MemoryStream(); { EmitResult compileResult = compilation.Emit(stream); try { compiledAssembly = Assembly.Load(stream.GetBuffer()); } catch { return null; } stream = null; } return compiledAssembly; } } }